<!DOCTYPE html>
<html>
<head>
    <title>组合模式</title>
    <meta charset="UTF-8"/>
    <link rel="stylesheet" type="text/css" href="../index.css"/>
</head>
<body>
<div class="container">
    <h3>组合模式</h3>
    <p>组合模式：事物是由相似的子事物构成。组合模式就是用小的子对象来构建更大的对象，而这些小的子对象本身也许是由更小的对象构成。</p>
    <span class="span-click-btn" id="btn1">命令模式的 多重组合</span><br><br>
    <span class="span-click-btn" id="btn2">扫描文件夹</span><br><br>
    <span class="span-click-btn" id="btn3">子对象引用父对象</span>
</div>
<script type="text/javascript">
    (function(window) {
        // 在命令模式中有一个宏命令是这样写的
        /*var closeDoorCommand = {
            execute: function() {
                console.log('关门')
            }
        }

        var openPcCommand = {
            execute: function() {
                console.log('开电脑')
            }
        }

        var openQQCommand = {
            execute: function() {
                console.log('登录QQ')
            }
        }

        var MacroCommand = function() {
            return {
                commandList: [],
                add: function(command) {
                    this.commandList.push(command)
                },

                execute: function() {
                    for (var i = 0, command; command = this.commandList[i++];) {
                        command.execute();
                    }
                }
            }
        }

        var macroCommand = MacroCommand();
        macroCommand.add(closeDoorCommand)
        macroCommand.add(openPcCommand)
        macroCommand.add(openQQCommand)
        macroCommand.execute();
        // macroCommand 是一个宏任务对象， 它的组成是由许多的子任务组成*/


        // 命令模式的 多重组合
        // 回家后
        // 1 打开空调
        // 2 打开电视同时需要打开音响
        // 3 关门 打开电脑 登录QQ
        /*var MacroCommand = function() {
            return {
                commandList: [],
                add: function(command) {
                    this.commandList.push(command)
                },

                execute: function() {
                    for (var i = 0, command; command = this.commandList[i++];) {
                        command.execute();
                    }
                }
            }
        }


        var openAcCommand = {
            execute: function() {
                console.log('打开空调')
            }
        }

        var openTVCommand = {
            execute: function() {
                console.log('打开电视')
            }
        }

        var openSoundCommand = {
            execute: function() {
                console.log('打开音响')
            }
        }

        var closeDootCommand = {
            execute: function() {
                console.log('关门')
            }
        }

        var openPCCommand = {
            execute: function() {
                console.log('打开电脑')
            }
        }

        var openQQCommand = {
            execute: function() {
                console.log('打开QQ')
            }
        }

        var commands1 = MacroCommand();
        commands1.add(openTVCommand);
        commands1.add(openSoundCommand);
        var commands2 = MacroCommand();
        commands2.add(closeDootCommand);
        commands2.add(openPCCommand);
        commands2.add(openQQCommand);

        var commandCollection = MacroCommand();
        commandCollection.add(openAcCommand);
        commandCollection.add(commands1);
        commandCollection.add(commands2);

        btn1.onclick = (function(command) {
            return function() {
                command.execute();
            }
        })(commandCollection)*/

        // 组合模式的例子--扫描文件夹
        // 1. 定义文件夹Folder与文件File这两个类
        /*var Folder =  function(name) {
            this.name = name;
            this.files = [];
        }

        Folder.prototype.add = function(file) {
            this.files.push(file)
        }

        Folder.prototype.scan = function() {
            console.log('开始扫描文件夹：' + this.name);
            for (var i = 0, file; file = this.files[i++];) {
                file.scan()
            }
        }

        var File = function(name) {
            this.name = name;
        }

        File.prototype.add = function() {
            throw new Error('文件下边不能再添加文件')
        }

        File.prototype.scan = function() {
            console.log('已扫描到文件：' + this.name)
        }

        // 1 创建最外层的 学习资料 文件夹
        // 2 创建两个分类文件夹 javascript jquery
        // 3 创建 几本 相关书籍并添加到对应文件夹
        var folder = new Folder('学习资料');
        var folder1 = new Folder('javascript');
        var folder2 = new Folder('jquery');

        var file1 = new File('javascript 红宝书');
        var file2 = new File('javascript设计模式');
        var file3 = new File('精通Jquery');
        var file4 = new File('重构与模式');

        // 在不同分类的文件夹下添加相关的书籍
        folder1.add(file1);
        folder1.add(file2);
        folder2.add(file3);
        // 将不同的学习文件归纳学习资料中
        folder.add(folder1);
        folder.add(folder2);
        // file4 同样可以归类到 学习资料中
        folder.add(file4);
        // 假设在其他文件夹中已经得到一个文件夹 node
        // 在该文件夹下存在基本数
        var folder3 = new Folder('node.js');
        var file5 = new File('深入浅出Node.js');
        folder3.add(file5);

        folder.add(folder3);

        btn2.onclick = function() {
            folder.scan();
        }*/


        // 子对象引用父对象
        // 当我们再删除某个对象时  我们需要在其父元素上进行删除
        // 在子对象中通过this.parent字段应用父对象
        var Folder = function(name) {
            this.name = name;
            this.parent = null;
            this.files = [];
        }

        Folder.prototype.add = function(file) {
            file.parent = this;
            this.files.push(file)
        }

        Folder.prototype.scan = function() {
            console.log('开始扫描文件夹：' + this.name);
            for (var i = 0, file, files = this.files; file = files[i++];) {
                file.scan();
            }
        }

        Folder.prototype.remove = function() {
            if (!this.parent) {
                return;
            }

            for (var files = this.parent.files, l = this.parent.files.length; l >= 0; l--) {
                var file = files[l];
                if (file === this) {
                    files.splice(l, 1)
                }
            }
        }

        var File = function(name) {
            this.name = name;
            this.parent = null;
        }

        File.prototype.add = function() {
            throw new Error( '不能添加在文件下面' );
        }

        File.prototype.scan = function() {
            console.log('开始扫描文件: ' + this.name)
        }

        File.prototype.remove = function() {
            if (!this.parent) {
                return;
            }

            for (var files = this.parent.files, l = this.parent.files.length; l >= 0; l--) {
                var file = files[l];
                if (file === this) {
                    files.splice(l, 1)
                }
            }
        }

        var folder = new Folder('学习资料');
        var folder1 = new Folder('JavaScript');
        var file1 = new File('深入浅出Node.js');
        folder1.add(new File('JavaScript设计模式与开发实践'));
        folder.add(folder1);
        folder.add(file1);
        folder1.remove();
        btn3.onclick = function() {
            folder.scan();
        }
    })(window)
</script>
<script type="text/javascript" src="composite.js"></script>
</body>
</html>